package com.shujia

object Demo10Func4 {
  /**
   * 函数作为返回值：同样也会有类型的限制
   *
   */
  def main(args: Array[String]): Unit = {
    // 调用
    // 返回了一个函数
    val f2: Int => Int = func1("100")
    val i: Int = f2(10)
    println(i) // 110

    // 直接一步调用
    println(func1("200")(20)) // 220
    println(func3("300")(30)) // 330
    println(func2_1("400", 40)) // 440

    a_pow_b(2, 3)
    a_pow_b(3, 2)
    a_pow_b(3)

    // 计算 4、5、6、7 的 2次方
    // 因为函数在定义时 默认参数为 3 只能默认计算 a的3次方
    // 这里2不能省略
    a_pow_b(4, 2)
    a_pow_b(5, 2)
    a_pow_b(6, 2)
    a_pow_b(7, 2)


    a_pow_b_2(3)(2)
    a_pow_b_2(2)(3)

    // 使用函数式编程的思想 动态地固定参数 简化调用
    val a_2: Int => Unit = a_pow_b_2(2)
    a_2(4)
    a_2(5)
    a_2(6)
    a_2(7)


  }

  // 以函数作为返回值时 返回值类型需要手动指定
  def func1(str: String): Int => Int = {
    def func2(int: Int) = {
      str.toInt + int
    }

    func2
  }

  // 这是一个有N个参数的函数
  def func2_1(str: String, int: Int): Int = {
    str.toInt + int
  }

  // func1的简化定义
  // func2_1 --> func3 柯里化
  // 一个有N个参数的函数 --> N个只有一个参数的函数
  def func3(str: String)(int: Int): Int = {
    str.toInt + int
  }

  /**
   * 计算a的b次方，如果只传入a则默认计算a的3次方
   */

  // 第一种方式：使用默认参数
  // 偏应用函数：将有N个参数的函数 --> N-X个参数的函数，X表示所固定的参数
  def a_pow_b(a: Int, b: Int = 3): Unit = {
    println(Math.pow(a, b))
  }

  // 第二种方式：使用函数式编程思想
  def a_pow_b_2(b: Int)(a: Int): Unit = {
    println(Math.pow(a, b))
  }

}
